package cn.itcast.nems.manager.util;

import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import okhttp3.*;
import org.apache.http.HttpStatus;
import org.apache.http.util.TextUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

public class OkHttpUtil {

    private static final Logger log = LoggerFactory.getLogger(OkHttpUtil.class);
    //    private static final OkHttpClient client = new OkHttpClient.Builder()
    //            // 设置超时时间
    //            .readTimeout(10, TimeUnit.MINUTES)
    //            .build();
    private static final OkHttpClient client = new OkHttpClient.Builder()
            // 设置超时时间
            .connectTimeout(60, TimeUnit.SECONDS)
            .readTimeout(60, TimeUnit.SECONDS)
            .writeTimeout(60, TimeUnit.SECONDS).build();
    public static final MediaType MEDIA_TYPE_JSON = MediaType.get("application/json; charset=utf-8");


    /**
     * 发起 Post请求, 使用form表单参数
     *
     * @param url    url
     * @param params 参数
     * @return 响应结果
     */
    public static String doPost(String url, Map<String, Object> params) {
        Call call = createPostCall(url, params);
        return execute(call);
    }

    /**
     * 发起 Post请求, 使用form表单参数
     *
     * @param url    url
     * @param params 参数
     * @return 响应结果
     */
    public static String doPost(String url, Map<String, Object> params, String loginUser) {
        Call call = createPostCall(url, params, loginUser);
        return execute(call);
    }

    /**
     * 发起 Post请求, 使用form表单参数
     *
     * @param url     url
     * @param json    参数
     * @param headers 请求头
     * @return 响应结果
     */
    public static String doPost(String url, String json, Map<String, String> headers) throws IOException, RuntimeException {
        log.info("【okhttp 发起Post请求】URL：{} , json：{} ，headers：{}", url, json, JSON.toJSONString(headers, SerializerFeature.DisableCircularReferenceDetect));
        Call call = createPostCall(url, json, headers);
        return execute(call);
    }

    /**
     * 发起 post请求, 使用json参数
     *
     * @param url  url
     * @param json json参数
     * @return resp
     */
    public static String doPost(String url, String json) {
        log.info("[发起POST请求], 参数 url: {}, request_body: {}", url, json);
        Call call = createPostJsonCall(url, json);
        return execute(call);
    }

    /**
     * [异步] 发起 Post请求
     *
     * @param url    url
     * @param params 参数
     */
    public static void doPostAsync(String url, Map<String, Object> params, Callback callback) {
        Call call = createPostCall(url, params);
        call.enqueue(callback);
    }

    /**
     * [异步] 发起 post请求, 使用json参数
     *
     * @param url  url
     * @param json json参数
     */
    public static void doPostAsync(String url, String json, Callback callback) {
        Call call = createPostJsonCall(url, json);
        call.enqueue(callback);
    }


    /**
     * Post请求, 构造 Call对象
     *
     * @param url    请求url
     * @param params 请求参数
     * @return Call
     */
    private static Call createPostCall(String url, Map<String, Object> params) {
        Request request = new Request.Builder()
                .post(createFormBody(params))
                .url(url)
                .build();
        return client.newCall(request);
    }

    /**
     * Post请求, 构造 Call对象
     *
     * @param url    请求url
     * @param params 请求参数
     * @return Call
     */
    private static Call createPostCall(String url, Map<String, Object> params, String loginUser) {
        log.info("[post请求头] login_user: {}", loginUser);
        Request request = new Request.Builder()
                .header("login_user", loginUser)
                .post(createFormBody(params))
                .url(url)
                .build();
        return client.newCall(request);
    }

    /**
     * Post请求, 构造 Call对象
     *
     * @param url  请求url
     * @param json 请求参数
     * @return Call
     */
    private static Call createPostCall(String url, String json, Map<String, String> headers) {
        log.info("[post请求头] headers: {}", headers);
        Request request = new Request.Builder()
                .headers(setHeaderParams(headers))
                .post(RequestBody.create(MEDIA_TYPE_JSON, json))
                .url(url)
                .build();
        return client.newCall(request);
    }

    /**
     * Post请求, 构造 Call对象
     *
     * @param url  请求url
     * @param json 请求参数
     * @return Call
     */
    private static Call createPostJsonCall(String url, String json) {
        Request request = new Request.Builder()
                .post(RequestBody.create(MEDIA_TYPE_JSON, json))
                .url(url)
                .build();
        return client.newCall(request);
    }


    /**
     * 为 get请求设置参数
     *
     * @param request request对象
     * @param params  请求参数
     * @return 设置了参数的 HttpUrl对象
     */
    private static HttpUrl createHttpUrl(Request request, Map<String, Object> params) {
        HttpUrl.Builder urlBuilder = request.url().newBuilder();
        if (params != null && !params.isEmpty()) {
            for (Map.Entry<String, Object> entry : params.entrySet()) {
                urlBuilder.addQueryParameter(entry.getKey(), String.valueOf(entry.getValue()));
            }
        }
        return urlBuilder.build();
    }


    /**
     * 为 post请求设置参数
     *
     * @param params 请求参数
     * @return FormBody
     */
    private static FormBody createFormBody(Map<String, Object> params) {
        FormBody.Builder builder = new FormBody.Builder();
        if (params != null && !params.isEmpty()) {
            for (Map.Entry<String, Object> entry : params.entrySet()) {
                if (Objects.nonNull(entry.getValue())) {
                    builder.add(entry.getKey(), String.valueOf(entry.getValue()));
                }
            }
        }
        return builder.build();
    }

    /**
     * get 请求到目标服务器
     *
     * @param url     请求地址
     * @param headMap 请求头
     * @return 响应信息
     */
    public static String doGet(String url, Map<String, String> headMap) {
        Headers headers = setHeaderParams(headMap);
        log.info("请求地址：{}， 头部参数：{}", url, JSON.toJSONString(headMap));
        Request request = new Request.Builder().url(url).headers(headers).get().build();
        Call call = client.newCall(request);
        String result = "";
        return returnHandler(call, result);
    }

    /**
     * 添加headers
     *
     * @param headerParams
     * @return
     */
    private static Headers setHeaderParams(Map<String, String> headerParams) {
        Headers headers = null;
        Headers.Builder headersbuilder = new Headers.Builder();
        if (CollectionUtil.isNotEmpty(headerParams)) {
            for (String key : headerParams.keySet()) {
                if (!TextUtils.isEmpty(key) && !TextUtils.isEmpty(headerParams.get(key))) {
                    // 如果参数不是null并且不是""，就拼接起来
                    headersbuilder.add(key, headerParams.get(key));
                }
            }
        }
        headers = headersbuilder.build();
        return headers;
    }

    private static String returnHandler(Call call, String result) {
        try {
            Response response = call.execute();
            if (HttpStatus.SC_OK != response.code()) {
                throw new RuntimeException("okHttp 调用远程服务异常，状态码：" + response.code());
            }
            result = response.body().string();
            log.info("请求返回：{}", result);
        } catch (Exception e) {
            log.error("okHttp 请求 异常:", e);
        } finally {
            return result;
        }
    }


    /**
     * 同步执行 http请求
     *
     * @param call call对象
     * @return 响应结果
     */
    public static String execute(Call call) {
        try {
            String respStr = "";
            Response response = call.execute();
            ResponseBody body = response.body();
            if (body != null) {
                log.info("同步执行 http请求 响应正文：{}", body);
                respStr = body.string();
            }
            if (response.code() != HttpStatus.SC_OK) {
                throw new RuntimeException(!respStr.isEmpty() ? respStr : "请求异常");
            }
            //        if(!respStr.startsWith("[")  && respStr.startsWith("{")) {
            //            JSONObject jsonObject = JSON.parseObject(respStr);
            //            Boolean isSuccess = jsonObject.getBoolean("success");
            //            if (Objects.nonNull(isSuccess) && !isSuccess) {
            //                String errorMessage = jsonObject.getString("errorMessage");
            //                throw new RuntimeException(StringUtils.hasText(errorMessage) ? errorMessage : "请求异常");
            //            }
            //        }
            return respStr;
        } catch (Exception e) {
            throw new RuntimeException(e.getMessage(), e);
        }
    }

}